import java.util.Arrays;

/**
 * Created by Dominik on 2014-10-18.
 */
public class Hand {

    public static int HAND_SIZE = 4;
    private int[] hand = new int[HAND_SIZE];


    Hand(Deck deck, Player player) {

        for (int i = 0; i < HAND_SIZE; i++) {
            hand[i] = -1; // -1 is for lack of card here
        }
        for (int i = 0; i < HAND_SIZE; i++) {
            try {
                drawCard(deck, player.getNumber());
            } catch (Exception e) {
                System.out.println(e.getMessage());
                System.out.println("Coś tu nie gra");
            }
        }
    }



    public static int[] getReducedHand(int[] hand) {
        int[][][] collisionMatrix = new int [hand.length][hand.length][];
        boolean collisionExist = false;
        for (int i = 0; i < hand.length; i++) {
            for (int j = 0; j < hand.length; j++) {
                if ((i != j) && (hand[i] / 13 == hand[j] / 13 || hand[i] % 13 == hand[j] % 13)) {
                    collisionExist = true;
                    int[] reducedHandCandidate = new int[hand.length - 1];
                    for (int k = 0; k < reducedHandCandidate.length; k++) {
                        if (k < i)
                            reducedHandCandidate[k] = hand[k];
                        else
                            reducedHandCandidate[k] = hand[k + 1];
                    }
                        collisionMatrix[i][j] = getReducedHand(reducedHandCandidate);
                }
                else collisionMatrix[i][j] = new int[]{-2, -2, -2, -2};
            }
        }
        if (collisionExist) {
            int[] bestHand = new int[]{-1,-1,-1,-1};
            for (int i = 0; i < hand.length; i++) {
                for (int j = 0; j < hand.length; j++) {
                    if(!Arrays.equals(collisionMatrix[i][j], new int[]{-2, -2, -2, -2}))
                        if(Arrays.equals(bestHand, new int[]{-1, -1, -1, -1}))
                            bestHand = collisionMatrix[i][j];
                        else {
                            bestHand = giveBetterHand(bestHand, collisionMatrix[i][j]);
                        }
                }
            }
            return bestHand;
        }
        else
            return hand;
    }

        public static int [] giveBetterHand (int [] handOne, int[] handTwo) {
            if(handOne.length > handTwo.length)
                return handOne;
            if(handOne.length < handTwo.length)
                return handTwo;
            int [] cardsFromOne = new int [handOne.length];
            int [] cardsFromTwo = new int [handTwo.length];
            for(int i = 0; i < handOne.length; i++) {
                cardsFromOne[i] = handOne[i]%13;
                cardsFromTwo[i] = handTwo[i]%13;
            }
            Arrays.sort(cardsFromOne);
            Arrays.sort(cardsFromOne);
            for(int i = handOne.length - 1; i >= 0; i--) {
                if(cardsFromOne[i] < cardsFromTwo[i])
                    return handOne;
                if(cardsFromOne[i] > cardsFromTwo[i])
                    return handTwo;
            }
            return handOne;
        }

    public void drawCard(Deck deck, int playerNumber) throws Exception {
        boolean isFull = true;
        for (int i = 0; i < HAND_SIZE; i++) {
            if (hand[i] == -1)
                isFull = false;
        }
        if (isFull) throw new Exception("Can't draw next card");
        int i = 0;
        while (hand[i] != -1) {
            i++;
        }
        hand[i] = deck.giveCard(playerNumber);
    }


    /*
    cardSet is binary representation of cards player want to discard e.g.
    we have cards: A|B|C|D and want to discard B then cardSet := 0100(2) = 4
    if we want to discard A and C the cardSet will be 1001(2) = 9
     */
    public int[] discardCards(Deck deck, int cardSet){
        int[] discardedCards = new int[Integer.bitCount(cardSet)]; //Number of "1" in cardSet binary representation equals length of the array

        for (int i = HAND_SIZE - 1; i >= 0; i--) {
            if (cardSet % 2 == 1) {
                for (int j = 0; j < discardedCards.length; j++) {
                    if (discardedCards[j] != 0)
                        discardedCards[j] = hand[i];
                }
                deck.returnCardToDeck(hand[i]);
                hand[i] = -1;
            }
            cardSet /= 2;
        }
        return discardedCards;
    }

    public void changeCards(Deck deck, int playerNumber, int cardSet){
        int[] discardedCards = discardCards(deck, cardSet);
        for (int i = 0; i < discardedCards.length; i++) {
            try
                        {
                                this.drawCard(deck, playerNumber);
                        } catch (Exception e)
                        {
                                e.getMessage();
                        }
        }
    }

    public int[] getCards() {
        return hand;
    }
   
    public String getString(){
        String s = "";
        for (int i=0; i<HAND_SIZE; i++){
                s = s + getOneCard(i);
        }
        return s;
    }
    /**
     * return "00","01"...."09"..."51"
     * @param index
     * @return
     */
    public String getOneCard(int index){
        if(hand[index]<10){
                return ("0" + Integer.toString(hand[index]));
        }
        else{
                return Integer.toString(hand[index]);
        }
    }
   

}